// DlgMain.cpp : implementation file
//

#include "stdafx.h"
#include "TravianAutoTask.h"
#include "DlgMain.h"
#include "AboutDlg.h"

//CEventLog g_TravianEvtLog(NULL, _T("TravianAutoTask"));

// CDlgMain dialog

IMPLEMENT_DYNAMIC(CDlgMain, CDialog)

CDlgMain::CDlgMain(CWnd* pParent /*=NULL*/)
	: CDialog(CDlgMain::IDD, pParent)
	, m_sUsr(_T(""))
	, m_sPwd(_T(""))
	, m_sSvr(_T(""))
	, m_sTaskFileName(_T(""))
	, m_pThread(NULL)
	, m_sRichEditNewContent(_T(""))
	, m_pts(NULL)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAIN);	
}

CDlgMain::~CDlgMain()
{
	if (m_pts)
	{
		CTravianTask::ClearTasks(*m_pts);
		delete m_pts;
	}
}

void CDlgMain::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_USR, m_sUsr);
	DDX_Text(pDX, IDC_PWD, m_sPwd);
	DDX_Text(pDX, IDC_SVR, m_sSvr);
	DDX_Text(pDX, IDC_TASKFILENAME, m_sTaskFileName);
	DDX_Control(pDX, IDC_RICHEDIT_OUTPUT, m_reOutput);
}


BEGIN_MESSAGE_MAP(CDlgMain, CDialog)
	ON_BN_CLICKED(IDOK, &CDlgMain::OnBnClickedOk)
	ON_BN_CLICKED(IDC_RADIO_SHUTDOWN, &CDlgMain::OnBnClickedRadioShutdown)
	ON_BN_CLICKED(IDC_RADIO_CLOSE, &CDlgMain::OnBnClickedRadioClose)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_SYSCOMMAND()
	ON_MESSAGE (WM_USERMSG_TASK_SETPARAM_FINISHED,	&CDlgMain::OnTaskSetParamFinished)
	ON_MESSAGE (WM_USERMSG_TASK_EXECSTATE,			&CDlgMain::OnTaskExecState)
	ON_MESSAGE (WM_USERMSG_SCHEDULE_FINISHED,		&CDlgMain::OnScheduleFinished)
	ON_MESSAGE (WM_USERMSG_NEWEVENTLOG,				&CDlgMain::OnNewEventLog)	
	//ON_WM_CLOSE()
	ON_BN_CLICKED(IDC_BTN_BROWSE,					&CDlgMain::OnBnClickedBtnBrowse)
END_MESSAGE_MAP()



// CDlgMain message handlers

BOOL CDlgMain::OnInitDialog()
{
	CDialog::OnInitDialog();

	// TODO:  Add extra initialization here

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		pSysMenu->AppendMenu(MF_SEPARATOR);
		pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, _T("About Travian Auto-Task..."));
	}

	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// Set Rich Edit background color to light green
	GetDlgItem(IDC_RICHEDIT_OUTPUT)->PostMessage(EM_SETBKGNDCOLOR, 0, RGB(204, 255, 204));

	g_TravianEvtLog.SetOutputWnd(m_hWnd);
	g_TravianEvtLog.OpenLogFile();

	GetDlgItem(IDC_USR)->ShowWindow(SW_SHOW);
	GetDlgItem(IDC_PWD)->ShowWindow(SW_SHOW);
	GetDlgItem(IDOK)->ShowWindow(SW_SHOW);

#ifdef TEST
	//OnBnClickedOk();
#endif

	return TRUE;
	// EXCEPTION: OCX Property Pages should return FALSE
}




void CDlgMain::OnBnClickedOk()
{
	// TODO: Add your control notification handler code here
#ifdef TEST
	((CButton*)(GetDlgItem(IDC_RADIO_SHUTDOWN)))->SetCheck(BST_UNCHECKED);
	((CButton*)(GetDlgItem(IDC_RADIO_CLOSE)))->SetCheck(BST_CHECKED);
	m_sSvr = _T("s1.travian.cn");
	m_sTaskFileName = _T("new_ tasks.txt");
	m_sUsr = _T("Hewitt");
	m_sPwd = _T("aling780226");
	UpdateData(FALSE);
#endif

	UpdateData(TRUE);
	if (m_sSvr.GetLength() <=0 || m_sUsr.GetLength() <=0 || m_sPwd.GetLength() <=0 ||
		m_sTaskFileName.GetLength() <=0 )
	{
		AfxMessageBox(_T("Please input server, task file name, user name and password!"), MB_OK | MB_ICONERROR);
		return;
	}

	bool bInit = false;
	if (!m_pThread)
	{
		bInit = true;

		// Create schedule thread. The thread is created suspended so that we can
		// set variables in CThreadSchedule before it starts executing.
		m_pThread = (CThreadSchedule*)AfxBeginThread(RUNTIME_CLASS(CThreadSchedule), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
		if (!m_pThread)
		{
			AfxMessageBox(_T("Could not create connection thread\n"), MB_ICONSTOP);
			return;
		}
		
		//if (!m_pThread->InitSchedule(&g_TravianEvtLog, m_hWnd, m_sSvr, m_sUsr, m_sPwd, m_sTaskFileName))
		//{
		//	PostQuitMessage(0);
		//	return ;
		//}
		m_pThread->ResumeThread();
	}

	CThreadSchedule::ScheduleParam* pParam = new CThreadSchedule::ScheduleParam();
	pParam->SetWnd(this->m_hWnd);
	pParam->SetEventLog(&g_TravianEvtLog);
	pParam->SetSvr(m_sSvr);
	pParam->SetUserPwd(m_sUsr, m_sPwd);
	pParam->SetTaskFileName(m_sTaskFileName);
	if ( ((CButton*)(GetDlgItem(IDC_RADIO_SHUTDOWN)))->GetCheck() == BST_CHECKED )
		pParam->SetAction(E_ACTION_SHUTDOWN);
	if (  ((CButton*)(GetDlgItem(IDC_RADIO_CLOSE)))->GetCheck() == BST_CHECKED )
		pParam->SetAction(E_ACTION_EXIT);

	if (bInit)
		::PostThreadMessage(m_pThread->m_nThreadID, WM_THREADMSG_SCHEDULE_INIT, 0, 0);
	::PostThreadMessage(m_pThread->m_nThreadID, WM_THREADMSG_SCHEDULE_SETPARAM, 0, (LPARAM)pParam);

	GetDlgItem(IDC_USER)->EnableWindow(FALSE);
	GetDlgItem(IDC_PWD)->EnableWindow(FALSE);
	GetDlgItem(IDC_SVR)->EnableWindow(FALSE);
	GetDlgItem(IDC_TASKFILENAME)->EnableWindow(FALSE);
	GetDlgItem(IDC_BTN_BROWSE)->EnableWindow(FALSE);
	GetDlgItem(IDOK)->EnableWindow(FALSE);


	return ;  // return TRUE unless you set the focus to a control
}
void CDlgMain::OnBnClickedRadioShutdown()
{
	// TODO: Add your control notification handler code here
	CThreadSchedule::ScheduleParam* pParam = new CThreadSchedule::ScheduleParam();
	if ( ((CButton*)(GetDlgItem(IDC_RADIO_SHUTDOWN)))->GetCheck() == BST_CHECKED )
		pParam->SetAction(E_ACTION_SHUTDOWN);
	else
		pParam->SetAction(E_ACTION_EXIT);

	::PostThreadMessage(m_pThread->m_nThreadID, WM_THREADMSG_SCHEDULE_SETPARAM, 0, (LPARAM)pParam);

}

void CDlgMain::OnBnClickedRadioClose()
{
	// TODO: Add your control notification handler code here
	CThreadSchedule::ScheduleParam* pParam = new CThreadSchedule::ScheduleParam();
	if ( ((CButton*)(GetDlgItem(IDC_RADIO_CLOSE)))->GetCheck() == BST_CHECKED )
		pParam->SetAction(E_ACTION_EXIT);
	else
		pParam->SetAction(E_ACTION_SHUTDOWN);

	::PostThreadMessage(m_pThread->m_nThreadID, WM_THREADMSG_SCHEDULE_SETPARAM, 0, (LPARAM)pParam);

}

LRESULT CDlgMain::OnTaskSetParamFinished(WPARAM wParam, LPARAM lParam)
{
	// wParam indicates whether tasks parameter set successful(1) or failed(0). 
	// LPARAM is the pointer of returned Tasks object, user needs to delete this object if he doesn't use it. 
	// This message only sent when set tasks file name parameter instead of other parameters. 
	if (wParam)
	{
		m_pts = (Tasks*)lParam;
		::PostThreadMessage(m_pThread->m_nThreadID, WM_THREADMSG_SCHEDULE_START, 0, 0);
	}
	else
	{
		AfxMessageBox(_T("Task file parsing failed."), MB_ICONSTOP);
		
		GetDlgItem(IDC_USR)->EnableWindow(TRUE);
		GetDlgItem(IDC_PWD)->EnableWindow(TRUE);
		GetDlgItem(IDC_SVR)->EnableWindow(TRUE);
		GetDlgItem(IDC_TASKFILENAME)->EnableWindow(TRUE);
		GetDlgItem(IDC_BTN_BROWSE)->EnableWindow(TRUE);
		GetDlgItem(IDOK)->EnableWindow(TRUE);
	}
	return 0;
}

LRESULT CDlgMain::OnScheduleFinished (WPARAM wParam, LPARAM lParam)
{
	DWORD nThreadID = (DWORD)lParam;

	GetDlgItem(IDC_USR)->EnableWindow(TRUE);
	GetDlgItem(IDC_PWD)->EnableWindow(TRUE);
	GetDlgItem(IDC_SVR)->EnableWindow(TRUE);
	GetDlgItem(IDC_TASKFILENAME)->EnableWindow(TRUE);
	GetDlgItem(IDC_BTN_BROWSE)->EnableWindow(TRUE);
	GetDlgItem(IDOK)->EnableWindow(TRUE);

	return 0;
}

LRESULT CDlgMain::OnTaskExecState(WPARAM wParam, LPARAM lParam)
{

	return 0;
}

// EditStreamCallback not work for frenquently append new content.
static DWORD CALLBACK EditStreamInCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
	CString* psNewContent = (CString*)dwCookie;

	int nLen = psNewContent->GetLength();
	if (nLen <=0 ) return 0;

	int nLeft = nLen - cb;
	if (nLeft <=0)
		cb = nLen;

	memcpy(pbBuff, (LPCTSTR)(*psNewContent), cb);
	*pcb =cb;

	if (nLeft > 0)		
		(*psNewContent) = psNewContent->Right(nLeft);
	else
		(*psNewContent).Empty();

	return 0;
}


LRESULT CDlgMain::OnNewEventLog (WPARAM wParam, LPARAM lParam)
{
	long nNewEvtCnt = (long)lParam;
	System::EventLog::EVENTLOG* pNewEvt = new System::EventLog::EVENTLOG[nNewEvtCnt];

	g_TravianEvtLog.FetchEvt(pNewEvt, nNewEvtCnt);
	CString sLog, sTemp;
	for (int i=0; i<nNewEvtCnt; i++)
	{
		g_TravianEvtLog.FormatEvtString( (pNewEvt+i)->nEvtLevel, (pNewEvt+i)->sEvt, sTemp);
		sTemp += _T("\n");
		sLog += sTemp;
	}
	delete [] pNewEvt;

//	m_sRichEditNewContent += sLog;
//	EDITSTREAM es;
//	es.dwCookie = (DWORD_PTR) (&m_sRichEditNewContent);
//	es.pfnCallback = EditStreamInCallback; 
//#ifndef UNICODE
//	m_reOutput.StreamIn(SF_TEXT, es);
//#else
//	m_reOutput.StreamIn(SF_TEXT | SF_UNICODE, es);
//#endif

	int nOldLines = m_reOutput.GetLineCount();
	long lInsertionPoint = m_reOutput.GetWindowTextLength();
	// Replace selection. Because we have nothing 
	// selected, this will simply insert
	// the string at the current caret position.
	m_reOutput.SetSel(lInsertionPoint,-1);
	m_reOutput.ReplaceSel(sLog);

	// Get new line count
	int nNewLines = m_reOutput.GetLineCount();
	// Scroll by the number of lines just inserted
	int nScroll = nNewLines - nOldLines;
	m_reOutput.LineScroll(nScroll);

	return 0;
}


void CDlgMain::OnCancel()
{
	// TODO: Add your specialized code here and/or call the base class
	if (m_pThread)
		::PostThreadMessage(m_pThread->m_nThreadID, WM_QUIT,0,0);	
	CDialog::OnCancel();
}
void CDlgMain::OnBnClickedBtnBrowse()
{
	// TODO: Add your control notification handler code here
	CFileDialog dlg(TRUE, _T("txt"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		_T("Text files(*.txt)|*.txt|All files(*.*)|*.*||"), NULL);

	BOOL bRet = FALSE;
	if (dlg.DoModal() == IDOK)
	{
		GetDlgItem(IDC_TASKFILENAME)->SetWindowText(dlg.GetPathName());
		UpdateData(TRUE);
	}
}

void CDlgMain::OnPaint()
{
	// TODO: Add your message handler code here
	// Do not call CDialog::OnPaint() for painting messages

	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}

}

HCURSOR CDlgMain::OnQueryDragIcon()
{
	// TODO: Add your message handler code here and/or call default

	//return CDialog::OnQueryDragIcon();
	return (HCURSOR) m_hIcon;
}

void CDlgMain::OnSysCommand(UINT nID, LPARAM lParam)
{
	// TODO: Add your message handler code here and/or call default

	//CDialog::OnSysCommand(nID, lParam);
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}




